#include "istring.h"

#include <map>
#include <mutex>
#include <vector>

namespace anagram_optimizer {
namespace {
class StringLookup {
 public:
  size_t Get(const std::string& s) {
    std::lock_guard<std::mutex> l(mutex_);
    if (string_to_index_.find(s) != string_to_index_.end()) {
      return string_to_index_[s];
    }
    index_to_string_.push_back(s);
    string_to_index_[s] = index_to_string_.size() - 1;
    return index_to_string_.size() - 1;
  }

  const std::string& Reverse(size_t index) {
    std::lock_guard<std::mutex> l(mutex_);
    return index_to_string_[index];
  }

 private:
  std::mutex mutex_;  // Guards both map and vector.
  std::map<std::string, size_t> string_to_index_;
  std::vector<std::string> index_to_string_;
};

StringLookup& GetLookup() {
  static StringLookup lookup;
  return lookup;
}
}  // namespace

istring::istring(const std::string& s) : index_(GetLookup().Get(s)) {}
istring::istring(const char* s) : index_(GetLookup().Get(s)) {}

const std::string& istring::as_string() const {
  return GetLookup().Reverse(index_);
}


}  // namespace anagram_optimizer
